• sed编辑器可以根据命令来处理数据流中的数据,这些命令要么从命令行中输入,要么存储在一个命令文本文件中,sed编辑器会执行下列操作:

    • 一次从输入中读取一行数据
    • 根据所提供的编辑器命令匹配数据
    • 按照命令修改流中的数据
    • 将新的数据输出到STDOUT

    在流编辑器将所有命令与一行数据匹配完毕后,它会读取下一行数据并重复这个过程,当处理完所有数据后,它就会终止,sed命令的格式如下:sed options script file

    选项允许你修改sed命令的行为:

    • -e script 在处理输入时,将script中指定的命令添加到已有的命令中
    • -f file 在处理输入时,将file中指定的命令添加到已有的命令中
    • -n 不产生命令输出,使用print命令来完成输出

    script参数指定了应用于数据流上的单个命令,如果需要多个命令,要么使用-e选项在命令行中指定,要么使用-f选项在单独的文件中指定。

  • 默认情况下,sed编辑器会将指定的命令应用到STDIN数据流上,可以直接将数据通过管道输入sed编辑器处理:

    echo “This is a test” | sed ‘s/test/big test/‘

    This is a big test

    这个例子在sed编辑器中使用了s命令,s命令会用斜线间指定的第二个文本字符串来替换第一个文本字符串模式,需要注意的是sed编辑器并不会修改文本文件的数据,它只会将修改后的数据发送到STDOUT中。

  • 要在sed命令行中执行多个命令时,只要用-e选项就可以了:

    sed -e 's/brown/green/; s/dog/cat/' data1.txt

    两个命令都作用到文件中的每一行数据中,命令之间用分号隔开,并且在命令末尾和分号之间不能有空格,如果不想用分号,只要在命令行中输入第一个单引号标示出sed程序脚本的起始,bash会继续提示你输入更多命令,直到输入了标示结束的单引号:

    1
    2
    3
    4
    sed -e '
    > s/brown/green/
    > s/fox/elephant/
    > s/dog/cat/' data1.txt
  • 可以在sed命令中通过-f选项来指定sed文件:

    1
    sed -f script1.sed data1.txt
  • 替换命令(s)在替换多行中的文本时能正常工作,但默认情况下它只替换每行出现的第一处,要让替换命令能够替换一行中不同地方出现的文本必须使用替换标记,替换标记会在替换字符串之后设置:

    1
    s/pattern/replacement/flags

    有4种可用的替换标记:

    • 数字,表明新文本将替换第几处模式匹配的地方
    • g,表明新文本将会替换所有匹配的文本
    • p,表明原先行的内容要打印出来
    • w file, 将替换的结果写入到文件中

    p替换标记会打印与替换命令中指定的模式匹配的行,这通常会和sed的-n选项一起使用,-n选项会禁止sed编辑器输出,但p标记会输出修改过的行,将二者配合使用的效果就是只输出被替换命令修改过的行

  • 如果你想用C shell替换/etc/passwd文件中的bash shell,必须这么做:

    1
    sed 's/\/bin\/bash/\/bin\/csh' /etc/passwd

    由于正斜线通过用作字符串分隔符,因而出现在模式文本中的话,必须用反斜线来转义,要解决这个问题,sed编辑器允许选择其他字符来作为替换命令中的字符串分隔符:

    1
    sed 's!/bin/bash!/bin/csh!' /etc/passwd
  • 默认情况下,sed编辑器中使用的命令会作用与文本数据的所有行,如果只想命令作用于特定行或某些行,则必须使用行寻址,在sed编辑器中有两种形式的行寻址:

    • 以数字形式表示行区间
    • 用文本模式来过滤出行

    两种形式都使用相同的格式来指定地址:

    1
    [address]command

    也可以将特定地址的多个命令分组:

    1
    2
    3
    4
    5
    address {
    command1
    command2
    command3
    }

    sed编辑器会将指定的每条命令作用到匹配指定地址的行上。

  • 数字方式的行寻址

    sed编辑器会将文本流中的第一行编号为1,然后继续按顺序为接下来的行分配行号,在命令中指定的地址可以是单个行号,或是用起始行号、逗号、结尾行号指定的一定区间范围的行。

    1
    sed '2s/dog/cat/' data1.txt (sed编辑器只修改地址指定的第二行的文本)
    1
    sed '2,3s/dog/cat/' data1.txt (sed编辑器将修改地址指定的二、三行的文本)

    如果想将命令作用到文本中从某行开始的所有行,可以用特殊地址-美元符

    1
    sed '2,$s/dog/cat/' data1.txt
  • 使用文本模式过滤器

    sed编辑器允许指定文本模式来过滤出命令要作用的行:

    1
    /pattern/command

    必须用正斜线将要指定的pattern封起来,sed编辑器会将该命令作用到指定文本模式的行上:

    1
    sed '/Samantha/s/bash/csh' /etc/password

    上面这条命令将会将/etc/password文件中Samantha用户的bash改为csh

  • 如果需要在单行上指定多条命令,可以用花括号将多条命令组合在一起:

    1
    2
    3
    4
    sed '2{
    > s/fox/elephant/
    > s/dog/cat/
    }' data1.txt
  • 删除命令d会删除匹配指定寻址模式的所有行,当和指定地址一起使用时,可以从数据流中删除特定的文本行,例如:

    1
    sed '3d' data.txt

    也可以使用两个文本模式来删除某个区间内的行,你指定的第一个模式会打开行删除功能,第二个模式会关闭行删除功能,sed编辑器会删除两个指定行之间的所有行:

    1
    sed '/1/,/3/d' data.txt

    指定完上面的命令后,文本文件中出现1和3之间的行以及它们之间的行都会被删除,需要注意的是只要在sed编辑器在数据流中匹配了开始模式,删除功能就会打开,这可能会导致意外。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ cat data7.txt
    This is line number 1.
    This is line number 2.
    This is line number 3.
    This is line number 4.
    This is line number 1 again.
    This is text you want to keep.
    This is the last line in the file.
    $ sed '/1/,/3/d' data7.txt
    This is line number 4

    第二个出现数字”1”的行再次触发了删除命令,因为没有找到停止模式,所以就将数据流中的剩余行全部删除。

  • 插入和附加文本

  • 插入命令(i): 在指定行前增加一个新行

    • 附加命令(a): 在指定行后增加一个新行

    格式如下:

    1
    sed '[address]command\new line'

    new line中的文本将会出现在sed编辑器输出中你指定的位置,例如:

    1
    echo "Test line 2" | sed 'i\Test line 1'

    运行结果如下:

    1
    2
    Test line 1
    Test line 2

    下面是一个将一个新行插入到数据流第三行前:

    1
    sed '3i\This is an inserted line.' data.txt

    如果你有一个多行数据流,想要将新行附加到数据流的末尾,只要用代表数据最后一行的美元符就可以了:

    1
    sed '$a\This is a new line of text.' data.txt

    要插入或附加多行文本,就必须对要插入或附加的文本中的每一行使用反斜线,直到最后一行:

    1
    2
    3
    sed '1i\
    > This is one line of new text.\
    > This is another line of new text.' data.txt
  • 修改行

    1
    sed '3c\This is a changed line of text.' data.txt

    当然也可以用文本模式来寻址:

    1
    sed '/number 3/c\This is a changed line of text.' data.txt

    你也可以在修改命令中使用地址区间:

    1
    sed '2,3c\This is a new line of text.'data.txt

    sed编辑器会用这一行文本来替换数据流中的两行文本,而不是逐一修改这两行文本。

  • 转换命令:

    转换命令(y)是唯一一个可以处理单个字符的sed编辑器命令,格式如下:

    1
    [address]y/inchars/outchars/

    转换命令会对inchars和outchars进行一对一的映射,inchars中的第一个字符会被转换为outchars中的第一个字符,第二个字符会被转换成outchars中的第二个字符,如果两者长度不同会报错。

    1
    sed 'y/123/789/' data.txt

    转换命令是一个全局命令,也就是说它会文本行中找到的所有指定字符自动进行转换,而不会考虑它们出现的位置:

    1
    2
    echo "This 1 is a test of 1 try." | sed 'y/123/456'
    This 4 is a test of 4 try.
  • 跟替换命令中的p标记类似,p命令可以打印sed编辑器输出中的一行:

    1
    $ echo "this is a test" | sed 'p'

    输出结果如下:

    1
    2
    this is a test
    this is a test

    它所做的就是打印已有的数据文本,打印命令最常见的用法就是打印包含匹配文本模式的行:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ cat data6.txt
    This is line number 1.
    This is line number 2.
    This is line number 3.
    This is line number 4.
    $
    $ sed -n '/number 3/p' data6.txt
    This is line number 3.
    $

    在命令行上用-n选项,你可以禁止输出其他行,只打印包含匹配文本模式的行。

    如果需要在修改之前查看行:

    1
    2
    3
    4
    sed -n '/3/{
    > p
    > s/line/test/p
    > }' data.txt

    输出结果如下:

    1
    2
    This is line number 3.
    This is test number 3.

    sed编辑器命令会查找包含数字3的行,然后执行两条命令。首先,脚本用p命令来打印出原始行;然后它用s命令替换文本,并用p标记打印出替换结果。输出同时显示了原来的行文本和新的行文本。

  • 等号命令会打印行在数据流中的当前行号,每次数据流中出现一个换行符,sed编辑器就会认为一行文本结束了。

    如果你要在数据流中查找特定文本模式的话:

    1
    2
    3
    4
    sed -n '/number 4/{
    > =
    > p
    > }' data.txt

    输出结果如下:

    1
    2
    4
    This is line number 4

    利用-n选项,就能让sed编辑器只显示包含匹配文本模式的行的行号和文本。

  • 列出行

    列出命令(l)可以打印数据流中的文本和不可打印的ASCII字符,任何不可打印的字符要么在其八进制前加一个反斜线,要么使用标准C风格的命名法,比如\t:

    1
    2
    3
    4
    5
    6
    $ cat data9.txt
    This line contains tabs.
    $
    $ sed -n 'l' data9.txt
    This\tline\tcontains\ttabs.$
    $

    行尾的美元符表示换行符

  • 写入文件

    w命令用来向文件写入行:

    1
    [address]w filename

    filename可以使用相对路径或绝对路径,但不管是哪种,运行sed编辑器的用户必须有文件的写权限:

    1
    sed '1,2w test.txt' data.txt

    执行上面的命令后会将data.txt文件中一二行写入到test.txt中

  • 读取文件

    读取命令(r)允许你将一个独立文件的数据插入到数据流中:

    1
    [address]r filename
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ cat data12.txt
    This is an added line.
    This is the second added line.
    $
    $ sed '3r data12.txt' data6.txt
    This is line number 1.
    This is line number 2.
    This is line number 3.
    This is an added line.
    This is the second added line.
    This is line number 4.
    $

    同样的方法在使用文本模式地址时也适用。

    1
    2
    3
    4
    5
    6
    7
    8
    $ sed '/number 2/r data12.txt' data6.txt
    This is line number 1.
    This is line number 2.
    This is an added line.
    This is the second added line.
    This is line number 3.
    This is line number 4.
    $

    如果你要在数据流的末尾添加文本,只需用美元符地址符就行了。

    1
    2
    3
    4
    5
    6
    7
    8
    sed '$r data12.txt' data6.txt
    This is line number 1.
    This is line number 2.
    This is line number 3.
    This is line number 4.
    This is an added line.
    This is the second added line.
    $